// src/utils/locationAuth.ts
import Taro from '@tarojs/taro';

const SCOPE = 'scope.userLocation' as const;
const BLOCK_KEY = 'LOC_AUTH_BLOCK_UNTIL';
const BLOCK_MS = 48 * 60 * 60 * 1000; // 48h

const now = () => Date.now();

export const isBlocked = (): boolean => {
  const until = Number(Taro.getStorageSync(BLOCK_KEY) || 0);
  return until > now();
};

export const setBlock48hFromNow = () => {
  Taro.setStorageSync(BLOCK_KEY, now() + BLOCK_MS);
};

export const clearBlock = () => {
  Taro.removeStorageSync(BLOCK_KEY);
};

type EnsureOpts = {
  /** 强制提示去设置：忽略 48h 免打扰，并直接弹自定义弹窗而不是调用 authorize */
  forcePrompt?: boolean;
  /** 忽略免打扰（一般和 forcePrompt 一起用） */
  bypassBlock?: boolean;
};

/** 抽取成函数，避免重复 */
async function promptOpenSetting(): Promise<boolean> {
  const { confirm } = await Taro.showModal({
    title: '定位授权',
    content: '用于展示附近门店与导航',
    confirmText: '前往设置',
    cancelText: '取消',
  });
  if (!confirm) {
    setBlock48hFromNow(); // 取消则从此刻重新计 48h
    return false;
  }
  const os = await Taro.openSetting();
  const ok = os.authSetting?.[SCOPE] === true;
  if (!ok) setBlock48hFromNow();
  else clearBlock();
  return ok;
}

/**
 * 确保定位权限
 * - 默认：尊重 48h 免打扰；首次尝试走 authorize，拒绝后弹自定义弹窗到设置
 * - forcePrompt: true 时：忽略免打扰，直接弹“前往设置”，不走 authorize
 */
export async function ensureLocationAuth(
  opts: EnsureOpts = {}
): Promise<boolean> {
  const { forcePrompt = false, bypassBlock = false } = opts;

  // 1) 不管免打扰与否，先读取当前真实授权状态
  const setting = await Taro.getSetting();
  const status = setting.authSetting?.[SCOPE];

  // 已经授权：直接通过，并清理免打扰标记（避免后续误伤）
  if (status === true) {
    clearBlock();
    return true;
  }

  // 2) 强制模式：用户主动触发，直接引导去设置
  if (forcePrompt) {
    return promptOpenSetting();
  }

  // 3) 未强制时再考虑免打扰：只抑制“打扰”，但不抑制“读取已授权”
  if (!bypassBlock && isBlocked()) {
    // 被免打扰命中：不弹窗、不 authorize，按未授权处理
    return false;
  }

  // 4) 首次（undefined）可尝试系统授权
  if (status === undefined) {
    try {
      await Taro.authorize({ scope: SCOPE });
      clearBlock();
      return true;
    } catch {
      // 授权失败，走自定义弹窗
    }
  }

  // 5) 已明确拒绝（false）或 authorize 失败：提示去设置页手动打开
  return promptOpenSetting();
}
